package com.andryu.base

import android.os.Process
import android.util.Log
import java.util.Collections
import java.util.LinkedList
import kotlin.math.min

object LogUtils {
    private const val TAG = "LearnTutorial"

    private var isLog = true
    fun setLog(state:Boolean){
        isLog = state
    }
    private fun toParamsString(vararg params: Any?): Array<Any>? {
        var stringParams: Array<Any>? = null
        if (params.isNotEmpty()) {
            stringParams = arrayOf(params.size)
            var i = 0
            for (param in params) {
                stringParams[i++] = param.toString()
            }
        }
        return stringParams
    }

    /**
     * 打印debug级别的日志
     *
     * @param msg    日期信息，参数采用{?}的形式， 例如 "这是个{?},继续打印其他参数"
     * @param params 参数信息，用来替换msg中的{?}
     */
    fun d(msg: String?, vararg params: Any?) {
        //是否在控制台写日志
        if (isLog) {
            val stringParam = toParamsString(*params)
            LoggerThread.d(TAG, msg, *(stringParam ?: emptyArray()))
        }
    }

    /**
     * 将消息重新组合格式化处理
     *
     * @param msg
     * @param params
     * @return
     */
    private fun msgFromParams(bf: StringBuffer, msg: String?, vararg params: Any?) {
        if (msg == null) {
            return
        }
        val msgArray = msg.split("\\{\\?\\}".toRegex()).dropLastWhile { it.isEmpty() }
            .toTypedArray()
        val minLen = min(msgArray.size.toDouble(), params.size.toDouble()).toInt()
        for (i in 0 until minLen) {
            val param = params[i]
            bf.append(msgArray[i]).append(param)
        }
        for (i in minLen until msgArray.size) {
            bf.append(msgArray[i])
        }
    }

    /**
     * 打印日志的线程.
     * 在这一新的线程中打印日志
     */
    private object LoggerThread  {
        //        private static LoggerThread instance;
        private val taskLogList = Collections.synchronizedList(LinkedList<Runnable>())

        /**
         * 同步锁
         */
        private val locker = Any()

        /**
         * 线程是否在跑，这里暂时不会停掉，由于单例模式
         */
        private var isRunning = false

        /**
         * 任务队列是否处于等待状态
         */
        private var isWait = false

        init {
            initThread()
        }

        fun d(tag: String?, msg: String?, vararg params: Any?) {
            taskLogList.add(Runnable {
                val bf = StringBuffer()
                msgFromParams(bf, msg, *params)
                Log.d(tag, bf.toString())
            })
            notifyLock()
        }

        fun i(tag: String?, msg: String?, vararg params: Any?) {
            taskLogList.add(Runnable {
                val bf = StringBuffer()
                msgFromParams(bf, msg, *params)
                Log.i(tag, bf.toString())
            })
            notifyLock()
        }

        fun e(tag: String?, msg: String?, e: Throwable?, vararg params: Any?) {
            taskLogList.add(Runnable {
                val bf = StringBuffer()
                msgFromParams(bf, msg, *params)
                Log.e(tag, bf.toString(), e)
            })
            notifyLock()
        }

        private fun setLowThreadPriority() {
            try {
                Process.setThreadPriority(Process.THREAD_PRIORITY_LOWEST)
                Thread.currentThread().priority = Thread.MIN_PRIORITY
            } catch (e: Throwable) {
            }
        }

        /**
         * 初始化线程
         */
        private fun initThread() {
            isRunning = true
            //Logger的实现已经有线程挂起逻辑、且日志频率极高，因此不能使用TaskManager的公共线程池，以避免阻塞其它业务task
            Thread({
                setLowThreadPriority()
                while (isRunning) {
                    try {
                        val logSize = taskLogList.size
                        if (logSize > 0) {
                            try {
                                val r = taskLogList.removeAt(0)
                                r.run()
                            } catch (e: Throwable) {
                            }
                        } else {
                            //没有数据，则等待
                            synchronized(locker) {
                                isWait = true
                                (locker as Object).wait()
                                isWait = false
                            }
                        }
                    } catch (e: InterruptedException) {
                    }
                }
            }, "Logger").start()
        }

        /**
         * 通知解锁，让日志任务开始
         */
        private fun notifyLock() {
            if (!isWait) {
                return
            }
            try {
                synchronized(locker) {
                    (locker as Object).notify()
                }
            } catch (e: Throwable) {
            }
        }
    }

}
